package com.yykj.tencent.im.server.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.pulsar.shade.org.eclipse.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @Description: http
 * @date: 2017年7月12日
 * @author: xuad
 */
public class HttpUtil {
	public static Logger logger = LoggerFactory.getLogger(HttpUtil.class);
	public final static int CONNECT_TIMEOUT = 30 * 1000;// connect_timeout 单位是毫秒
	public final static int READ_TIMEOUT = 200 * 1000;// read_timeout 单位是毫秒

	public static String post(String urlPath, HashMap<String, Object> dataParams) {
		return muiltPost(urlPath, dataParams);
	}
	
	public static String postHead(String urlPath, HashMap<String, Object> dataParams,
			HashMap<String, Object> headerParams) {
		return send(urlPath, dataParams, headerParams, "POST", false, null,null,null,false);
	}
	public static String post(String urlPath, HashMap<String, Object> dataParams,
			HashMap<String, Object> headerParams,HttpServletResponse response,HttpServletRequest request) {
		return send(urlPath, dataParams, headerParams, "POST", false, null,response,request,false);
	}

	public static String get(String urlPath, HashMap<String, Object> dataParams, HashMap<String, Object> headerParams, HttpServletResponse response) {
		return send(urlPath, dataParams, headerParams, "GET", false, null,response,null,false);
	}
	public static String get(String urlPath, HashMap<String, Object> dataParams, HashMap<String, Object> headerParams, HttpServletResponse response,HttpServletRequest request) {
		return send(urlPath, dataParams, headerParams, "GET", false, null,response,request,false);
	}
	public static String get(String urlPath, HashMap<String, Object> dataParams, HashMap<String, Object> headerParams) {
		return send(urlPath, dataParams, headerParams, "GET", false, null,null,null,false);
	}
	public static String isExist(String urlPath, HashMap<String, Object> dataParams,
			HashMap<String, Object> headerParams) {
		return send(urlPath, dataParams, headerParams, "GET", true, null,null,null,false);
	}


	
	public static String postNoProxy(String urlPath, HashMap<String, Object> dataParams,
			HashMap<String, Object> headerParams) {
		return send(urlPath, dataParams, headerParams, "POST", false, null,null,null,true);
	}
	public static String getNoProxy(String urlPath, HashMap<String, Object> dataParams, HashMap<String, Object> headerParams) {
		return send(urlPath, dataParams, headerParams, "GET", false, null,null,null,true);
	}
	/**
	 * @Description: 调用POST请求
	 * @date: 2017年7月12日
	 * @param urlPath
	 * @param dataParams
	 *            拼在URL后面的参数
	 * @param headerParams
	 *            放在header中的参数
	 * @return 此方法内部已经处理了异常,返回 null就表示出现异常,具体看日志
	 * @author: xuad
	 */
	public static String send(String urlPath, HashMap<String, Object> dataParams, HashMap<String, Object> headerParams,
			String method, boolean getResponseCode, String outPutStr,HttpServletResponse response,HttpServletRequest request,boolean isPrxoy) {

		StringBuilder sb = new StringBuilder("");
		String paramsStr = "";
		if (dataParams != null && dataParams.size() > 0) {
			for (String key : dataParams.keySet()) {
				String val = dataParams.get(key) == null ? "" : dataParams.get(key).toString();
				sb.append(key + "=" + val + "&");
			}
			paramsStr = sb.toString();
			paramsStr = paramsStr.substring(0, paramsStr.length() - 1);
		}
		if (!StringUtil.isBlank(paramsStr)) {
			if ("get".equals(method) || "GET".equals(method)) {
				String splitChar = "?";
				try {
					URL urlTmp = new URL(urlPath);
					if (!StringUtil.isBlank(urlTmp.getQuery())) {
						splitChar = "&";
					}
				} catch (MalformedURLException e1) {
					e1.printStackTrace();
				}
				urlPath = urlPath + splitChar + paramsStr;
			}
		}
		logger.info("☆开始调用第三方接口,method:" + method + "☆\r\n" + urlPath);
		logger.info("参数列表" + paramsStr + "\r\n");
		StringBuilder sbLog = new StringBuilder();
		BufferedReader br = null;
		HttpURLConnection conn = null;
		sb = new StringBuilder("");
		try {
			URL url = new URL(urlPath);
			trustAllHttpsCertificates();
			HttpsURLConnection.setDefaultHostnameVerifier(hv);
			conn = (HttpURLConnection)url.openConnection();
			if (request != null) {
				Enumeration<String> headerNames = request.getHeaderNames();
				while(headerNames.hasMoreElements()){
					String nextElement = headerNames.nextElement();
					conn.setRequestProperty(nextElement, request.getHeader(nextElement));
				}
				
				/*conn.setRequestProperty("client", request.getHeader("client"));
				conn.setRequestProperty("device", request.getHeader("device"));
				conn.setRequestProperty("version", request.getHeader("version"));*/
			}
			
			conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
			conn.setRequestProperty("connection", "Keep-Alive");
			if (headerParams != null && headerParams.size() > 0) {
				sbLog.append("\r\nheader里的数据\r\n");
				for (String key : headerParams.keySet()) {
					String val = headerParams.get(key) == null ? "" : headerParams.get(key).toString();
					conn.setRequestProperty(key, val);
					sbLog.append(key).append("=").append(val).append("\r\n");
				}
			}
			conn.setRequestMethod("POST");
			if ("get".equals(method) || "GET".equals(method)) {
				conn.setRequestMethod("GET");
			}
			conn.setConnectTimeout(CONNECT_TIMEOUT);
			conn.setReadTimeout(READ_TIMEOUT);
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setUseCaches(false);

			if ("POST".equals(method) || "post".equals(method)) {
				/*StringBuilder postData = new StringBuilder();
				if (dataParams != null && dataParams.size() > 0) {
					for (String key : dataParams.keySet()) {
						String val = dataParams.get(key) == null ? "" : dataParams.get(key).toString();
						postData.append(URLEncoder.encode(key,"UTF-8")).append("=").append(URLEncoder.encode(val,"UTF-8")).append("&");
					}
					if (postData.length() > 0) {
						postData = postData.deleteCharAt(postData.length()-1);
						OutputStream outputStream = conn.getOutputStream();
						outputStream.write(postData.toString().getBytes("UTF-8"));
						outputStream.flush();
						outputStream.close();
					}
				}*/
				
				OutputStream outputStream = conn.getOutputStream();
				outputStream.write(paramsStr.getBytes("UTF-8"));
				outputStream.flush();
				outputStream.close();
					
			}
			
			if (!StringUtil.isBlank(outPutStr)) {
				OutputStream outputStream = conn.getOutputStream();
				outputStream.write(outPutStr.getBytes("UTF-8"));
				outputStream.flush();
				outputStream.close();
			}
			
			if ("application/octet-stream".equals(conn.getContentType()) && response != null) {
				int len = 0;
				byte[] b = new byte[1024];
				String headerField = conn.getHeaderField("X-Params");
				response.setHeader("X-Params", headerField);
				InputStream is = null;
				ServletOutputStream os = null;
				try {
					is = conn.getInputStream();
					os = response.getOutputStream();
					while((len = is.read(b)) != -1){
						os.write(b,0,len);
					}
					os.flush();
					return null;
				} catch (Exception e) {
				}finally{
					try {
						if (os != null) {
							os.close();
						}
						if (is != null) {
							is.close();
						}
					} catch (Exception e2) {
						e2.getMessage();
					}
				}
			}
			if (getResponseCode) {
				sb.append(200);
			} else {
				br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
				String str = "";
				while ((str = br.readLine()) != null) {
					sb.append(str);
				}
			}
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
			sbLog.append("\r\n◆调用失败◆\r\n:超时");
		} catch (Exception e) {
			e.printStackTrace();
			sbLog.append("\r\n◆调用失败◆\r\n" + e.getMessage());
			logger.info(sbLog.toString());
		} finally {
			try {
				if (br != null) {
					br.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
				sbLog.append("\r\n关闭资源出现异常\r\n");
			}
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
		sbLog.append("\r\n☆调用成功☆\r\n返回:").append(sb.toString());
//		sbLog.append("\r\n☆调用成功☆\r\n");
		logger.info(sbLog.toString());
		if (sb.length() == 0) {
			return null;
		}
		return sb.toString();
		
	}
	/**
	 * 此方法用于远程服务器文件上传
	 * 
	 * @Description: 调用POST请求
	 * @date: 2017年7月12日
	 * @param urlPath
	 * @param fileName
	 *            文件名
	 * @param ByteArrayOutputStream
	 *            文件流
	 * @return 此方法内部已经处理了异常,返回 null就表示出现异常,具体看日志
	 * @author: xuad
	 */
	static String end = "\r\n";
	static String twoHyphens = "--";
	static String boundary = "---------------------------7e0ddlancetcc";
	static String response = "";

	public static String filePost(String urlPath, String fileName, String filePath,HashMap<String, Object> dataParams,String fileKey) {
		StringBuilder sb = new StringBuilder("");
		BufferedReader br = null;
		HttpURLConnection conn = null;
		FileInputStream fis = null;
		logger.info("☆开始文件上传☆\r\n" + urlPath + "--" + filePath);
		StringBuilder sbLog = new StringBuilder();
		try {
			URL url = new URL(urlPath);
			trustAllHttpsCertificates();
			HttpsURLConnection.setDefaultHostnameVerifier(hv);
			conn = (HttpURLConnection)url.openConnection();
			conn.setRequestMethod("POST");
			conn.setConnectTimeout(CONNECT_TIMEOUT);
			conn.setReadTimeout(READ_TIMEOUT);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "UTF-8");
//			conn.setRequestProperty("user-agent", "1214194b75d14e3faf5fb48978c7f9bc");
			conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
			DataOutputStream ds = new DataOutputStream(conn.getOutputStream());
			if (dataParams != null && dataParams.size() > 0) {
				for (String key : dataParams.keySet()) {
					String val = dataParams.get(key) == null ? "" : dataParams.get(key).toString();
					ds.writeBytes(twoHyphens + boundary + end);  
		            ds.writeBytes("Content-Disposition: form-data; name=\""+ key +"\""+end);  
		            ds.writeBytes(end);  
		            ds.writeBytes(val + end);
				}
			}
			
			// 写文件
			ds.writeBytes(twoHyphens + boundary + end);
			ds.writeBytes("Content-Disposition: form-data; " + "name=\""+ fileKey +"\"; " + "filename=\"");
			// 防止中文乱码
			ds.write(fileName.getBytes());
			ds.writeBytes("\"" + end);
			ds.writeBytes("Content-Type: image/png" + end);
			ds.writeBytes(end);

			byte[] b = new byte[1024];
			int len = 0;
			fis = new FileInputStream(filePath);
			while((len = fis.read(b)) != -1){
				ds.write(b,0,len);
			}
			
			ds.writeBytes(end);
			// fis.close();
			ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
			ds.writeBytes(end);
			ds.flush();
			br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
			String str = "";
			while ((str = br.readLine()) != null) {
				sb.append(str);
			}
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
			sbLog.append("\r\n◆调用失败◆\r\n:超时");
			logger.info(sbLog+"");
			return null;
		} catch (Exception e) {
			e.printStackTrace();
			sbLog.append("\r\n◆调用失败◆\r\n");
			logger.info(sbLog+"");
			return null;
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
				}
			}
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
				}
			}
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
		sbLog.append("\r\n☆调用成功☆\r\n第三方接口返回:").append(sb.toString());
		logger.info(sbLog+"");
		if (sb.length() == 0) {
			return null;
		}
		return sb.toString();
	}

	private static void trustAllHttpsCertificates() throws Exception {
		javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
		javax.net.ssl.TrustManager tm = new miTM();
		trustAllCerts[0] = tm;
		javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
		sc.init(null, trustAllCerts, null);
		HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
	}

	static class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
		@Override
		public java.security.cert.X509Certificate[] getAcceptedIssuers() {
			return null;
		}

		public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
			return true;
		}

		public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
			return true;
		}

		@Override
		public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
				throws java.security.cert.CertificateException {
			return;
		}

		@Override
		public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
				throws java.security.cert.CertificateException {
			return;
		}
	}
	
	public static HostnameVerifier hv = new HostnameVerifier() {  
        @Override
		public boolean verify(String urlHostName, SSLSession session) {  
            return true;  
        }  
    };  
    
    
    public static String jsonSend(String urlPath, HashMap<String, Object> dataParams, HashMap<String, Object> headerParams,
			String json) {

		StringBuilder sb = new StringBuilder("");
		
		logger.info("☆开始调用第三方接口,method:POST☆\r\n" + urlPath);
		logger.info("参数:" + json + "\r\n");
		StringBuilder sbLog = new StringBuilder();
		BufferedReader br = null;
		HttpURLConnection conn = null;
		sb = new StringBuilder("");
		try {
			URL url = new URL(urlPath);
			trustAllHttpsCertificates();
			HttpsURLConnection.setDefaultHostnameVerifier(hv);
			conn = (HttpURLConnection)url.openConnection();
			
			conn.setRequestProperty("Content-type", "application/json");
			conn.setRequestProperty("connection", "Keep-Alive");
			if (headerParams != null && headerParams.size() > 0) {
				sbLog.append("\r\nheader里的数据\r\n");
				for (String key : headerParams.keySet()) {
					String val = headerParams.get(key) == null ? "" : headerParams.get(key).toString();
					conn.setRequestProperty(key, val);
					sbLog.append(key).append("=").append(val).append("\r\n");
				}
			}
			conn.setRequestMethod("POST");
			
			conn.setConnectTimeout(CONNECT_TIMEOUT);
			conn.setReadTimeout(READ_TIMEOUT);
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setUseCaches(false);
			OutputStream outputStream = conn.getOutputStream();
			outputStream.write(json.getBytes("UTF-8"));
			outputStream.flush();
			outputStream.close();
			br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
			String str = "";
			while ((str = br.readLine()) != null) {
				sb.append(str);
			}
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
			sbLog.append("\r\n◆调用失败◆\r\n:超时");
		} catch (Exception e) {
			e.printStackTrace();
			sbLog.append("\r\n◆调用失败◆\r\n" + e.getMessage());
			logger.info(sbLog.toString());
		} finally {
			try {
				if (br != null) {
					br.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
				sbLog.append("\r\n关闭资源出现异常\r\n");
			}
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
		sbLog.append("\r\n☆调用成功☆\r\n返回:").append(sb.toString());
//		sbLog.append("\r\n☆调用成功☆\r\n");
		logger.info(sbLog.toString());
		if (sb.length() == 0) {
			return null;
		}
		return sb.toString();
		
	}
    
    
    
    /**
    	下载网络图片到指定文件夹下,文件名字和url相同,把jpg存成png
    	如 http://192.168.88.120:34101/ca8a0d28df40d2e39a15cf9d3b93fb62/0.p.jpg  下载下来就是 0.p.png
    */
    public static boolean getImage(String urlStr, String fileFolder) {
    	String fileName = urlStr.substring(urlStr.lastIndexOf("/") + 1).replace("jpg", "png");
		System.out.println("☆开始访问网络☆:" + urlStr);
		HttpURLConnection conn = null;
		BufferedInputStream bis = null;
		FileOutputStream fos = null;
		try {
			URL url = new URL(urlStr);
			conn = (HttpURLConnection)url.openConnection();
			conn.setConnectTimeout(10 * 1000);
			bis = new BufferedInputStream(conn.getInputStream());
			int len = 0;
			byte[] b = new byte[1024];
			fos = new FileOutputStream(fileFolder + "/" + fileName);
			while ((len = bis.read(b)) != -1) {
				fos.write(b, 0, len);
			}
			return true;
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}
    
    public static String muiltPost(String urlPath,HashMap<String, Object> dataParams) {
		StringBuilder sb = new StringBuilder("");
		BufferedReader br = null;
		HttpURLConnection conn = null;
		FileInputStream fis = null;
		String paramsStr = "";
		if (dataParams != null && dataParams.size() > 0) {
			for (String key : dataParams.keySet()) {
				String val = dataParams.get(key) == null ? "" : dataParams.get(key).toString();
				sb.append(key + "=" + val + "&");
			}
			paramsStr = sb.toString();
			paramsStr = paramsStr.substring(0, paramsStr.length() - 1);
		}
		
		logger.info("☆开始调用第三方接口muiltPost,method:POST☆\r\n" + urlPath);
		logger.info("参数列表\r\n" + paramsStr);
		sb = new StringBuilder("");
		StringBuilder sbLog = new StringBuilder();
		try {
			URL url = new URL(urlPath);
			trustAllHttpsCertificates();
			HttpsURLConnection.setDefaultHostnameVerifier(hv);
			conn = (HttpURLConnection)url.openConnection();
			conn.setRequestMethod("POST");
			conn.setConnectTimeout(CONNECT_TIMEOUT);
			conn.setReadTimeout(READ_TIMEOUT);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "UTF-8");
//			conn.setRequestProperty("user-agent", "1214194b75d14e3faf5fb48978c7f9bc");
			conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
			
			BufferedOutputStream ds = new BufferedOutputStream(conn.getOutputStream());
			if (dataParams != null && dataParams.size() > 0) {
				for (String key : dataParams.keySet()) {
					String val = dataParams.get(key) == null ? "" : dataParams.get(key).toString();
					ds.write((twoHyphens + boundary + end).getBytes());  
		            ds.write(("Content-Disposition: form-data; name=\""+ key +"\""+end).getBytes());  
		            ds.write(end.getBytes());  
		            ds.write((val + end).getBytes("UTF-8"));
				}
			}
			
			// 写文件
			ds.write((twoHyphens + boundary + twoHyphens).getBytes());
			// 写文件
//			ds.writeBytes(end);
			/*ds.writeBytes("Content-Disposition: form-data; " + "name=\""+ fileKey +"\"; " + "filename=\"");
			// 防止中文乱码
			ds.write(fileName.getBytes());
			ds.writeBytes("\"" + end);
			ds.writeBytes("Content-Type: image/png" + end);
			ds.writeBytes(end);

			byte[] b = new byte[1024];
			int len = 0;
			fis = new FileInputStream(filePath);
			while((len = fis.read(b)) != -1){
				ds.write(b,0,len);
			}
			
			ds.writeBytes(end);
			// fis.close();
			ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
			ds.writeBytes(end);*/
			ds.flush();
			br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
			String str = "";
			sb = new StringBuilder();
			while ((str = br.readLine()) != null) {
				sb.append(str);
			}
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
			sbLog.append("\r\n◆调用失败◆\r\n:超时");
			return null;
		} catch (Exception e) {
			e.printStackTrace();
			sbLog.append("\r\n◆调用失败◆\r\n");
			return null;
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
				}
			}
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
				}
			}
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
		sbLog.append("\r\n☆调用成功☆\r\n第三方接口返回:").append(sb.toString());
		logger.info(sbLog.toString());
		if (sb.length() == 0) {
			return null;
		}
		return sb.toString();
	}
}
